<?php

require_once dirname(__FILE__) . '/../../bootstrap.unit.php';
require_once FORAGE_APP_PATH . '/engine/solr/SolrEngine.php';
require_once FORAGE_APP_PATH . '/behaviours/geo/GeoQueryBehaviour.php';

class ForageSolrEngineTest extends ForageUnitTestCase
{
  private $solr;

  public function setUp()
  {
    $dsn    = '127.0.0.1:8080';
    $config = array();
    //$this->solr = new ForageSolrEngine();
    $this->solr = $this->getMock('ForageSolrEngine', array('sendSearch', 'sendUpdate'));
    $this->solr->initialize($dsn, $config);
  }

  public function getQueryResponseXml()
  {
    $return = <<<END_XML
<?xml version="1.0" encoding="UTF-8"?>
<response>
  <lst name="responseHeader">
    <int name="status">0</int>
    <lst name="params">
      <str name="start">0</str>
      <str name="q">blah</str>
      <str name="rows">20</str>
    </lst>
  </lst>
  <result name="response" numFound="2" start="0">
    <doc>
      <str name="title">List of freshwater aquarium invertebrate species</str>
      <str name="uid">11752</str>
    </doc>
    <doc>
      <str name="title">Seabrook Crisps</str>
      <str name="uid">1402676</str>
    </doc>
  </result>
</response>
END_XML;
    return $return;
  }

  public function getDocument()
  {
    $document = new ForageDocument();
    $document->add('uid', '11752', array('uid'=>true));
    $document->add('title', 'A title');

    return $document;
  }

  public function tearDown()
  {
    unset($this->solr);
  }

  public function testAddingDocument()
  {
    $doc = new ForageDocument();
    $doc->setProperty('boost', '1.5');
    
    $field = new ForageField('title', 'This is the title');
    $field->setProperty('boost', '2.0');
    $doc[] = $field;
    
    $field = new ForageField('preview', 'This is the preview and is usually a bit longer');
    $field->setProperty('boost', '1.5');
    $doc[] = $field;
    
    $xml = $this->solr->createAddDocument($doc);
    $this->assertRegExp('#<add>.*</add>#', $xml, 'should return an add document xml string');
  }

  public function testCreatingAnAddDocumentWithMoreThanOneOfTheSameNamedField()
  {
    $doc   = new ForageDocument();
    $doc->setProperty('boost', '1.5');
    
    $doc->add('title', 'This is the first title');
    $doc->add('title', 'This is the second title');
    
    $xml = $this->solr->createAddDocument($doc);
    $this->assertRegExp('#<field name="title">This is the first title.*<field name="title">This is the second title#', $xml);
  }

  public function testCreatingQuery()
  {
    $query = $this->solr->getQuery();
    $this->assertInstanceOf($query, 'ForageQuery');
    $this->assertInstanceOf($query, 'ForageSolrQuery');
  }

  public function testGeneratingBasicSearchQuery()
  {
    $this->solr->expects($this->once())
         ->method('sendSearch')
         ->with($this->equalTo('http://127.0.0.1:8080/solr/select/?q=blah&start=0&rows=10&fl=%2A%2Cscore'));
    $query = new ForageSolrQuery();
    $query->setQueryString('blah');
    try {
      $this->solr->search($query);
    } catch (Exception $e) {}
  }

  public function testGeneratingAFacetedQuery()
  {
    $this->solr->expects($this->once())
               ->method('sendSearch')
               ->with($this->equalTo('http://127.0.0.1:8080/solr/select/?q=foo&start=0&rows=10&fl=%2A%2Cscore&facet=true&facet.mincount=1&facet.field=colour'));
    $query = new ForageSolrQuery();
    $query->setFacetFields(array('colour'));
    $query->setQueryString('foo');
    try {
      $this->solr->search($query);
    } catch (Exception $e) {}
  }

  public function testGeneratingAFilteredFacetQuery()
  {
    $this->solr->expects($this->once())
               ->method('sendSearch')
               ->with($this->equalTo('http://127.0.0.1:8080/solr/select/?q=' . urlencode('+(foo) +colour:"blue"') . '&start=0&rows=10&fl=%2A%2Cscore&facet=true&facet.mincount=1&facet.field=colour'));
    $query = new ForageSolrQuery();
    $query->setFacetFields(array('colour'));
    $query->addFacetFilter('colour', 'blue');
    $query->setQueryString('foo');
    try {
      $this->solr->search($query);
    } catch (Exception $e) {}
  }

  public function testGeneratingASortedQuery()
  {
    $this->solr->expects($this->once())
               ->method('sendSearch')
               ->with($this->equalTo('http://127.0.0.1:8080/solr/select/?q=foo&start=0&rows=10&fl=%2A%2Cscore&sort=foo+asc'));
    $query = new ForageSolrQuery();
    $query->addSortField('foo', SORT_ASC);
    $query->setQueryString('foo');
    try {
      $this->solr->search($query);
    } catch (Exception $e) {}
  }

  public function testGeneratingAGeoQuery()
  {
    $this->solr->expects($this->once())
               ->method('sendSearch')
               ->with($this->equalTo('http://127.0.0.1:8080/solr/select/?q=foo&start=0&rows=10&fl=%2A%2Cscore&qt=geo&lat=51.2393&long=-0.1726&radius=1'));
    $query = new ForageSolrQuery();
    $query->addBehaviour(new ForageGeoQueryBehaviour());
    $query->setPoint(51.2393, -0.1726);
    $query->setRadius(1);
    $query->setQueryString('foo');
    try {
      $this->solr->search($query);
    } catch (Exception $e) {}
  }

  public function testSearchResponse()
  {
    $this->solr->expects($this->once())
         ->method('sendSearch')
         ->will($this->returnValue($this->getQueryResponseXml()));
    $query = new ForageSolrQuery();
    $query->setQueryString('blah');
    $response = $this->solr->search($query);
    $this->assertInstanceOf($response, 'ForageResponse');
    $this->assertEquals(2, $response->total);
  }

  public function testAddingADocument()
  {
    $this->solr->expects($this->once())
         ->method('sendUpdate')
         ->with($this->equalTo(
            "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n".
            "<add><doc><field name=\"uid\">11752</field><field name=\"title\">A title</field></doc></add>\n"
          )
        );
    $this->solr->add($this->getDocument());
  }

  public function testRemovingADocument()
  {
    $this->solr->expects($this->once())
               ->method('sendUpdate')
               ->with(
                 $this->equalTo(
                   '<?xml version="1.0" encoding="UTF-8"?>' . "\n".
                   '<delete><id>11752</id></delete>' . "\n"
                 )
               );
    $this->solr->remove($this->getDocument());
  }

  public function testSendingFlush()
  {
    $this->solr->expects($this->once())
         ->method('sendUpdate')
         ->with($this->equalTo(
            "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n".
            "<commit/>\n"
          )
        );
    $this->solr->flush();
  }
}
